﻿Imports System.IO
Imports System.Reflection
Imports XCLI_API

Public Class Plugin
    Implements XCLIPlugin


    ''BEGIN: Properties.
    Public ReadOnly Property CommonName() As String Implements XCLIPlugin.CommonName
        Get
            'return the name.
            Return "XCLI Plugin Manager"
        End Get
    End Property

   Public ReadOnly Property Description() As String Implements XCLIPlugin.Description
        Get
            Return "Core plugin to manage the installing/removing plugins, as well as rebuilding the plugin manifest file."
        End Get
    End Property

    Public ReadOnly Property Fullname() As String Implements XCLIPlugin.Fullname
        Get
            Return "xcli.core.plugin.dll"
        End Get
    End Property

    Public ReadOnly Property Author() As String Implements XCLIPlugin.Author
        Get
            Return "XCLI"
        End Get
    End Property

   Public ReadOnly Property Build() As String Implements XCLIPlugin.Build
        Get
            Return My.Application.Info.Version.Build
        End Get
    End Property

   Public ReadOnly Property Dependencies() As String Implements XCLIPlugin.Dependencies
        Get
            Return ""
        End Get
    End Property

     Public ReadOnly Property Keywords() As String Implements XCLIPlugin.Keywords
        Get
            Return "plugin"
        End Get
    End Property

    Public Sub CONSTRUCT(ByVal command As String, ByRef env() As String) Implements XCLIPlugin.CONSTRUCT
        Try
            Dim CommandArr() As String = command.Split(" ")
            If UBound(CommandArr) < 2 Then
                ReDim Preserve CommandArr(2)
                Array.Resize(CommandArr, 3)
            End If

            Select Case CommandArr(1)
                Case Is = "install"
                    install_plugin(CommandArr(2), env)
                Case Is = "remove"
                    remove_plugin(CommandArr(2), env)
                Case Is = "rebuild"
                    rebuild_PluginCache(env)
                Case Is = "rebuildcache"
                    rebuild_PluginCache(env)
            End Select

        Catch ex As Exception
            Console.WriteLine(ex.Message.ToString)
        End Try
    End Sub

    Public Sub HELP(ByVal commands As String, ByRef env() As String) Implements XCLIPlugin.HELP
        Console.WriteLine("Pseudo help for xcli.core.plugins.dll")
    End Sub

    ''Install Plugin
    Private Sub install_plugin(ByVal plugin_fullName As String, ByVal env() As String)
        Try
            Dim pluginpath As String = plugin_fullName
            If plugin_fullName.StartsWith("\") Then
                pluginpath = env(0) & plugin_fullName
            ElseIf Not plugin_fullName.Substring(1, 2) = ":\" Then
                pluginpath = env(0) & "\" & plugin_fullName
            End If
            If plugin_fullName = "" Then
                Console.WriteLine("Invalid number of parameters. The ""plugin"" command requires 2 parameters:")
                Console.WriteLine("- ""plugin [ACTION] [DLL_NAME]""")
            ElseIf System.IO.File.Exists(pluginpath) = False Then
                Console.WriteLine("Unable to find """ & plugin_fullName & """. Please specify the full path")
            Else
                If Not File.Exists(Environment.CurrentDirectory & "\plugin\" & plugin_fullName) Then
                    File.Copy(pluginpath, Environment.CurrentDirectory & "\plugin\" & plugin_fullName)
                End If

                Dim plugin() As xml.plugins = xml.Manifest_to_array()
                Dim asm As Assembly = Assembly.LoadFrom(Environment.CurrentDirectory & "\plugins\" & plugin_fullName)
                Dim myType As System.Type = asm.GetType(asm.GetName.Name + ".Plugin")
                Dim implementsXCLIPlugin As Boolean = GetType(XCLIPlugin).IsAssignableFrom(myType)
                If implementsXCLIPlugin Then
                    'Console.WriteLine(asm.GetName.Name + " is a valid plugin!")
                    Dim newPlugin As XCLIPlugin = CType(Activator.CreateInstance(myType), XCLIPlugin)
                    'Console.WriteLine(plugin.CommonName & plugin.Description)
                    Dim keywordstring As String = newPlugin.Keywords
                    Dim keywords() As String = keywordstring.Split(",")
                    Dim alreadyExists As Boolean = False

                    For Each word In keywords

                        For i As Integer = 0 To plugin.Length - 1
                            If word = plugin(i).name Then
                                alreadyExists = True
                            End If
                        Next
                        ReDim Preserve plugin(plugin.Length)
                        Dim length As Integer = plugin.Length
                        plugin(length - 1).name = word
                        plugin(length - 1).dll = plugin_fullName
                    Next


                    ''WRITE TO FILE TEMP
                    FileOpen(1, Environment.CurrentDirectory & "\array.txt", OpenMode.Output)
                    For i As Integer = 0 To plugin.Length - 1
                        PrintLine(1, plugin(i).name & "," & plugin(i).dll)
                    Next
                    FileClose(1)
                    ''END WRITE TO FILE TEMP

                    'attempt to create the new manifest
                    If alreadyExists = False Then
                        xml.create(plugin)
                    Else
                        Console.WriteLine("Error: The keywords used in this plugin are already in use. This plugin is incompatible with your XCLI.")
                    End If

                End If
            End If

        Catch ex As Exception
            Console.WriteLine(ex.Message.ToString)
        End Try

    End Sub

    ''Remove plugin
    Private Sub remove_plugin(ByVal plugin_fullName As String, ByRef env() As String)
        Dim pluginArr() As xml.plugins
        If Not plugin_fullName.Substring(plugin_fullName.Length - 4, 4) = ".dll" Then
            plugin_fullName = plugin_fullName & ".dll"
        End If
        'read from manifest
        pluginArr = xml.Manifest_to_array()

        For i As Integer = 0 To UBound(pluginArr)
            If pluginArr(i).dll = plugin_fullName Then
                Array.Clear(pluginArr, i, 1)
            End If
        Next

        Dim newplugins() As xml.plugins
        Dim inner As Integer = 0
        For count As Integer = 0 To UBound(pluginArr)
            If Not pluginArr(count).dll = Nothing Then
                ReDim Preserve newplugins(inner)
                newplugins(inner).name = pluginArr(count).name
                newplugins(inner).dll = pluginArr(count).dll

                inner = inner + 1
            End If
        Next

        'write out the new plugin list.
        xml.create(newplugins)

        Console.Write("Do you want to remove the file """ & plugin_fullName & """? (Y/N): ")
        Dim answer As String = Console.ReadLine.ToUpper


        If answer = "Y" Then
            File.Delete(env(1) & "\" & plugin_fullName)
            Console.WriteLine("Plugin file deleted.")
        End If

    End Sub

    ''Rebuild Cache
    Private Sub rebuild_PluginCache(ByRef env() As String)
        Try
            Dim plugins(0) As xml.plugins
            Dim di As New IO.DirectoryInfo(env(1))
            Dim diar1 As IO.FileInfo() = di.GetFiles("*.dll")
            Dim dra As IO.FileInfo
            Dim count As Integer = 0
            'list the names of all files in the specified directory
            For Each dra In diar1
                Dim asm As Assembly = Assembly.LoadFrom(dra.FullName)
                Dim myType As System.Type = asm.GetType(asm.GetName.Name + ".Plugin")
                Dim implementsXCLIPlugin As Boolean = GetType(XCLIPlugin).IsAssignableFrom(myType)
                If implementsXCLIPlugin Then
                    Dim plugin As XCLIPlugin = CType(Activator.CreateInstance(myType), XCLIPlugin)
                    Dim keywords As String = plugin.Keywords
                    Dim KWArr() As String = keywords.Split(",")
                    For i As Integer = 0 To UBound(KWArr)
                        ReDim Preserve plugins(count)
                        plugins(count).name = KWArr(i)
                        plugins(count).dll = dra.Name
                        count = count + 1
                    Next
                End If
            Next
            xml.create(plugins)
            Console.WriteLine("Plugin Manifest successfully rebuilt!")

        Catch ex As Exception
            Console.WriteLine(ex.Message.ToString)
        End Try
    End Sub


End Class
